home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * obget.c: Main program for ObGet.
- * Request patch data from the Oberheim synth and store it in
- * a disk file.
- * A part of OberSuite for the Commodore Amiga.
- *
- * Author: Daniel Barrett, barrett@cs.umass.edu.
- * Version: 1.0.
- * Copyright: None! This program is in the Public Domain.
- * Please share it with others.
- ***************************************************************************/
-
- #include "decl.h"
- #include "obget.h"
-
- char *version = "$VER: ObGet " VERSION " " VERDATE;
-
- /***************************************************************************
- * The main program.
- ***************************************************************************/
-
- main(argc, argv)
- int argc; char *argv[];
- {
- Enable_Abort = 0; /* Disable ^C aborts. */
- strcpy(programName, BaseName(argv[0])); /* Global variable. */
- thePrintStyle = VERBOSE; /* Global variable. */
- overwriteAll = FALSE; /* Global variable. */
-
- if (argc == 1)
- {
- ShortUsageMsg();
- BegForUsage();
- }
- else if ((argc == 2) && (!strcmp(argv[1], "?")))
- DetailedUsage();
- else if (argc < 3)
- ErrorMsg(ERROR_NUMARGS);
- else if (!HandleOptions(argc, argv))
- BegForUsage();
- else if (optind != argc-2)
- ErrorMsg(ERROR_NUMARGS);
- else
- ObGet(argv[optind], argv[optind+1]);
-
- exit(0);
- }
-
- /*
- * Request the given patch (specified by patchString) and store it in the
- * given file.
- */
-
- void ObGet(char *patchString, char *filename)
- {
- PATCHINFO pi;
-
- InitPatchInfo(&pi);
-
- pi.source = PI_SOURCE_MIDI;
- if (!SerialSetup())
- return;
-
- if (BreakUp(patchString, &pi))
- {
- if (!overwriteAll && DontOverwriteExistingFile(filename))
- ;
- else if (CtrlcCheck())
- ErrorMsg(ERROR_CTRLC);
- else if (!TransmitPatchInfo(&pi, filename))
- ErrorMsg(ERROR_FAILED);
- else
- ;
- }
-
- FreePatchInfo(&pi);
- SerialShutdown();
- }
-
-
- /*
- * Given a patch string like "s23" or "m95", break it into its components
- * ('s' or 'm', and the optional integer patch number).
- * Store these components in the PATCHINFO structure.
- * Return TRUE on success (else FALSE).
- */
-
- BOOL BreakUp(char *patchString, PATCHINFO *pi)
- {
- if ((!patchString) || (patchString[0] == '\0'))
- {
- ErrorMsg(ERROR_PATCHTYPE);
- return(FALSE);
- }
- else if (!FigureOutMode(pi, patchString[0]))
- return(FALSE);
- else if (!FigureOutPatchNumber(pi, patchString+1))
- return(FALSE);
- else
- return(TRUE);
- }
-
-
- /*
- * The modeLetter must be either MODE_SINGLE or MODE_MULTI.
- * From the letter, deduce the mode and mode name (string).
- * Return TRUE on success (else FALSE).
- */
-
- BOOL FigureOutMode(PATCHINFO *pi, char modeLetter)
- {
- if (toupper(modeLetter) == LETTER_SINGLE)
- {
- pi->mode = MODE_SINGLE;
- strcpy(pi->modeName, NAME_SINGLE);
- }
- else if (toupper(modeLetter) == LETTER_MULTI)
- {
- pi->mode = MODE_MULTI;
- strcpy(pi->modeName, NAME_MULTI);
- }
- else
- {
- ErrorMsg(ERROR_PATCHTYPE);
- return(FALSE);
- }
-
- return(TRUE);
- }
-
-
- /*
- * The string numString must be either empty (implying that all patches
- * should be transferred) or an integer between FIRST_PATCH and LAST_PATCH.
- * Anything else is illegal.
- * Store the patch number in the patchNum field of the PATCHINFO struct, and
- * put a "1" in the numPatches field.
- * If the string is empty, store ALL_PATCHES_NUM in the patchNum field,
- * and put ALL_PATCHES_NUM in the numPatches field.
- */
-
- BOOL FigureOutPatchNumber(PATCHINFO *pi, char *numString)
- {
- if (!numString)
- {
- ErrorMsg(ERROR_PATCHNUM);
- return(FALSE);
- }
- else if (!(*numString))
- {
- pi->patchNum = ALL_PATCHES_NUM;
- pi->numPatches = ALL_PATCHES_NUM;
- }
- else if (!AllDigits(numString))
- {
- ErrorMsg(ERROR_PATCHNUM);
- return(FALSE);
- }
- else
- {
- pi->patchNum = atoi(numString);
- if (Between(pi->patchNum, FIRST_PATCH, LAST_PATCH))
- pi->numPatches = 1L;
- else if (pi->patchNum == ALL_PATCHES_NUM)
- pi->numPatches = (long)ALL_PATCHES_NUM;
- else
- {
- ErrorMsg(ERROR_PATCHNUM);
- return(FALSE);
- }
- }
- return(TRUE);
- }
-
-
- /***************************************************************************
- * Handle the command-line options.
- ***************************************************************************/
-
- BOOL HandleOptions(int argc, char *argv[])
- {
- int c;
- short printed = 0; /* How many print options were chosen? */
-
- while ((c = getopt(argc, argv, options)) != EOF)
- {
- switch (c)
- {
- case OPT_SILENT:
- thePrintStyle = SILENT;
- printed++;
- break;
- case OPT_VERBOSE:
- thePrintStyle = VERBOSE;
- printed++;
- break;
- case OPT_DEADQUIET:
- thePrintStyle = DEADQUIET;
- printed++;
- break;
- case OPT_OVERWRITE:
- overwriteAll = TRUE;
- break;
- default:
- return(FALSE);
- }
- }
-
- if (printed > 1) /* Can't choose 2 print options. */
- ErrorMsg(ERROR_TWOPRINTS);
-
- return(printed <= 1);
- }
-
- /***************************************************************************
- * Transmit the PATCHINFO structure data to MIDI.
- ***************************************************************************/
-
- BOOL TransmitPatchInfo(PATCHINFO *pi, char *filename)
- {
- BOOL result = TRUE;
-
- /* This is still a hack, but better than before (slightly).
- * We set rightSize to be >= than what we'll need, based on
- * the mode. This wastes RAM for Xpander multi-patches, because
- * Matrix-12 multi-patch dumps are almost 2 times larger.
- * Note that in FigureOutInstrument(), we finally set rightSize
- * to its proper value. Take this into consideration when we
- * finally fix this hack.
- */
-
- pi->rightSize = (pi->mode == MODE_MULTI)
- ? MATRIX12_MULTI_SIZE
- : LARGEST_OBERHEIM_PATCHSIZE;
-
- if (! (result = AllocPatchInfo(pi)) )
- ErrorMsg(ERROR_MALLOC);
- else if (! (result = GetPatchFromMidi(pi)) )
- ErrorMsg(ERROR_GETFAILED);
- else if (! (result = PutPatchToFile(pi, filename)) )
- ErrorMsg(ERROR_PUTFAILED_SAVE);
-
- return(result);
- }
-
-
- /***************************************************************************
- * Usage information.
- ***************************************************************************/
-
-
- void ShortUsageMsg(void)
- {
- if (!ERR_OUTPUT_ALLOWED)
- return;
-
- fprintf(stderr, "Usage: %s [options] PATCH filename\n", programName);
- }
-
-
- void UsageMsg(void)
- {
- if (!ERR_OUTPUT_ALLOWED)
- return;
-
- fprintf(stderr, "%s grabs Xpander/Matrix-12 patch data"
- " and saves it in a file.\n",
- programName);
-
- ShortUsageMsg();
-
- fprintf(stderr, "\nLegal options are:\n");
- fprintf(stderr,
- "\t-%c:\tOverwrite existing files without asking permission.\n",
- OPT_OVERWRITE);
- fprintf(stderr, "\t-%c:\tQuiet output; error messages only.\n",
- OPT_SILENT);
- fprintf(stderr, "\t-%c:\tNo output; not even error messages.\n",
- OPT_DEADQUIET);
- fprintf(stderr, "\t-%c:\tLong output. (DEFAULT)\n",
- OPT_VERBOSE);
-
- fprintf(stderr, "\n\"PATCH\" may be any of the following forms:\n");
- fprintf(stderr, " One single patch:\t");
- fprintf(stderr, "The letter %c followed by a number between %d-%d.\n",
- LETTER_SINGLE, FIRST_PATCH, LAST_PATCH);
- fprintf(stderr, " One multi patch:\t");
- fprintf(stderr, "The letter %c followed by a number between %d-%d.\n",
- LETTER_MULTI, FIRST_PATCH, LAST_PATCH);
-
- fprintf(stderr,
- " All single patches:\tThe letter %c, or %c%d.\n",
- LETTER_SINGLE, LETTER_SINGLE, ALL_PATCHES_NUM);
- fprintf(stderr,
- " All multi patches:\tThe letter %c, or %c%d.\n",
- LETTER_MULTI, LETTER_MULTI, ALL_PATCHES_NUM);
-
- fprintf(stderr,
- "Upper and lower case are equivalent for '%c' and '%c'.\n",
- LETTER_SINGLE, LETTER_MULTI);
-
- fprintf(stderr, "Examples:\n");
- fprintf(stderr, "\t%s %c34 MyFile\n", programName, LETTER_SINGLE);
- fprintf(stderr, "\t%s %c MyFile\n", programName,
- tolower(LETTER_MULTI));
-
- }
-
-
- char *Version(void)
- {
- static char v[] = VERSION;
- return(v);
- }
-